/*************************************************************************
 *					SRLOS TEAM ALL RIGHT RESERVED
 *@filename		mmu_in_handle.c
 *@autor		bloceanc
 *@date			08/08/2010
 *@note			manager memory relations interrupt
 *@addition 	today id my birthday, happyed birthday to me 
 * 				allthouht along^_^
 ************************************************************************/

#include "mem_mmu_page.h"
#include "task.h"

extern k_process *g_current_process;

extern void mem_mmu_page_unpresent_handler(k_process *process, unsigned int vir_addr);
extern void mem_mmu_page_readonly_handler(k_process *process, unsigned int vir_address);

extern unsigned int k_cp15_c5_read_data_abort_status(void);
extern unsigned int k_cp15_c6_read_FAR(void);

/*
 *	get page AP value
 */
unsigned int getAP(unsigned int phy_flpt, unsigned int vir_addr)
{
	unsigned int *vir_flpt = (unsigned int *)COMM_MMU_SYSTEMPAGE_ADDRESS_PHY2VIR(phy_flpt);
	unsigned int phy_slpt = vir_flpt[vir_addr>>20]&0xfffffc00;
	unsigned int *vir_slpt = (unsigned int *)COMM_MMU_SYSTEMPAGE_ADDRESS_PHY2VIR(phy_slpt);
	return (((vir_slpt[(vir_addr<<12)>>24])>>4)&0x0ff0);
}

/*
 *	get page domain
 */
unsigned int getDomain(unsigned int phy_flpt, unsigned int vir_addr)
{
	unsigned int *vir_flpt = (unsigned int *)COMM_MMU_SYSTEMPAGE_ADDRESS_PHY2VIR(phy_flpt);
	return (vir_flpt[vir_addr>>20]>>5)&0xf;
}

/*
 *  mem exception handler
 */
void mem_data_abort_handler(void)
{
	/* get exception status */
	unsigned int status = k_cp15_c5_read_data_abort_status();
	unsigned int far = k_cp15_c6_read_FAR();
	switch(status)
	{
		case PAGE_FAULT_TYPE_VECTOR:
			{
			}
			break;
		case PAGE_FAULT_TYPE_EXTRANS_FIRST:
		case PAGE_FAULT_TYPE_EXTRANS_SECOND:
		case PAGE_FAULT_TYPE_TRANS_PAGE:
			{
				mem_mmu_page_unpresent_handler(g_current_process,far);
			}
			break;
		case PAGE_FAULT_TYPE_PERMISSION_PAGE:
			{
				// check whether this page is readonly, in other words, this exception caused by write readonly memory.
				if(!getAP(g_current_process->mem.mmu.pt_phy_address, far))
				{
					// this caused by readonly , when ap=0, this page is readonly in any mode.^_^.for more details see <arm920t architechure reference manual>
					mem_mmu_page_readonly_handler((void *)g_current_process->mem.mmu.pt_phy_address,far);
				}
			}
			break;
		case PAGE_FAULT_TYPE_DOMAIN_PAGE:
			{

			}
			break;
	}
}

